function getID(a) {
  //通过ID得到元素
  return document.getElementById(a);
}
function getEleAll(a) {
  //通过元素标签来得所有到元素
  return document.querySelectorAll(a);
}

function arrRemoval(arr) {
  //去重，可以取出数组和函数
  let result = [];
  let obj = {};
  for (let i of arr) {
    if (!obj[i]) {
      result.push(i);
      obj[i] = 1;
    }
  }
  return result;
}

// 工具类 js
/* 
    求最大值的函数 传入任意个参数 找到其中最大的那一个值
*/
function maxNum() {
  var max = arguments[0];
  for (var i = 1; i < arguments.length; i++) {
    if (arguments[i] > max) {
      max = arguments[i];
    }
  }
  return max;
}

/* 
    求最小值的函数 传入任意个参数 找到其中最小的那一个值
*/
function minNum() {
  var min = arguments[0];
  for (var i = 1; i < arguments.length; i++) {
    if (arguments[i] < min) {
      min = arguments[i];
    }
  }
  return min;
}

/* 
    求范围随机数的函数
    @param a 范围之间较小的那个数
    @param b 范围之间较大的那个数
    @return  得到的一个范围之间的随机数
*/
function getRandom(a, b) {
  return Math.floor(Math.random() * (b - a + 1) + a);
}

/* 
    求随机颜色的函数 
    @return 得到一个 rgb() 的一个字符串
*/
function getColor() {
  return `rgb(${getRandom(0, 255)},${getRandom(0, 255)},${getRandom(0, 255)})`;
}
/* 
    @param ele 要设置或者获取属性的元素
    @param attr 要设置或者获取的属性
    @param value 可选参数  要设置的属性值
    @return 获取到的元素的某一个属性值
*/

function setStyle(ele, attr, value) {
  if (typeof value === "undefined") {
    // 没有传入 value 这个参数 那么就是获取
    return window.getComputedStyle
      ? window.getComputedStyle(ele)[attr]
      : ele.currentStyle[attr];
  }
  ele.style[attr] = value;
}

/* 
    添加事件监听
    @param ele 要添加事件监听的元素
    @param type  事件的类型
    @param fn 事件处理函数
*/

function on(ele, type, fn) {
  if (ele.addEventListener) {
    // 应该判断事件类型有没有 on
    if (type.indexOf("on") == 0) {
      type = type.slice(2);
    }
    ele.addEventListener(type, fn);
  } else {
    if (type.indexOf("on") !== 0) {
      type = "on" + type;
    }
    ele.attachEvent(type, fn);
  }
}

/* 
    获取元素的不包含边框的宽度
    @param ele  要获取的元素
    @return 获取到的宽度
*/
function innerW(ele) {
  var res = css(ele, "display");
  if (res === "none") {
    return (
      parseFloat(css(ele, "width")) +
      parseFloat(css(ele, "paddingLeft")) +
      parseFloat(css(ele, "paddingRight"))
    );
  }
  return ele.clientWidth;
}
/* 
  获取元素的不包含边框的高度
  @param ele  要获取的元素
  @return 获取到的高度
*/
function innerH(ele) {
  var res = css(ele, "display");
  if (res === "none") {
    return (
      parseFloat(css(ele, "height")) +
      parseFloat(css(ele, "paddingTop")) +
      parseFloat(css(ele, "paddingBottom"))
    );
  }
  return ele.clientHeight;
}
/* 
    获取元素的实际宽度
    @param ele  要获取的元素
    @return 获取到的宽度
*/
function outerW(ele) {
  var res = css(ele, "display");
  if (res === "none") {
    return (
      parseFloat(css(ele, "width")) +
      parseFloat(css(ele, "paddingLeft")) +
      parseFloat(css(ele, "paddingRight")) +
      parseFloat(css(ele, "borderLeftWidth")) +
      parseFloat(css(ele, "borderRightWidth"))
    );
  }
  return ele.offsetWidth;
}
/* 
  获取元素的实际高度
  @param ele  要获取的元素
  @return 获取到的高度
*/
function outerW(ele) {
  var res = css(ele, "display");
  if (res === "none") {
    return (
      parseFloat(css(ele, "height")) +
      parseFloat(css(ele, "paddingTop")) +
      parseFloat(css(ele, "paddingBottom")) +
      parseFloat(css(ele, "borderTopWidth")) +
      parseFloat(css(ele, "borderBottomWidth"))
    );
  }
  return ele.offsetWidth;
}
// function $(selector, context) {
//   context = context || document;
//   if (selector.indexOf("#") == 0) {
//     return document.getElementById(selector.slice(1));
//   }
//   if (selector.indexOf(".") == 0) {
//     return context.getElementsByClassName(selector.slice(1));
//   }
//   return context.getElementsByTagName(selector);
// }

/* 
  @param ele 要设置或者获取属性的元素
  @param attr 要设置或者获取的属性
  @param value 可选参数  要设置的属性值
  @return 获取到的元素的某一个属性值
*/
function css(ele, attr, value) {
  if (typeof value === "undefined") {
    // 没有传入 value 这个参数 那么就是获取
    return window.getComputedStyle
      ? window.getComputedStyle(ele)[attr]
      : ele.currentStyle[attr];
  }
  ele.style[attr] = value;
}
/* 
  光标到页面左右的距离
  @param e event对象
  @return {x:...,y:....}
*/
function page(e) {
  if (e.pageX) {
    return { x: e.pageX, y: e.pageY };
  }
  var _left = document.documentElement
    ? document.documentElement.scrollLeft + e.clientX
    : document.body.scrollLeft + e.clientX;
  var _top = document.documentElement
    ? document.documentElement.scrollTop + e.clientY
    : document.body.scrollTop + e.clientY;
  return {
    x: parseInt(_left),
    y: parseInt(_top)
  };
}
/*
可以拖动  没有限制边界

*/
drag = ele => {
  var ele = ele;
  // console.log(ele);
  ele.onmousedown = () => {
    fn(ele);
  };
};
fn = ele => {
  fn1 = (_x, _y) => {
    // console.log(ele);
    var e = e || window.event;
    e.preventDefault(); //-->清除默认  避免div内有文字  或者重叠等出现无法拖拽，松开后继续跟随的情况
    let x = e.clientX - _x;
    let y = e.clientY - _y;
    ele.style.left = x + "px";
    ele.style.top = y + "px";
  };
  var e = e || window.event;
  let _x = e.offsetX;
  let _y = e.offsetY;
  fn2 = () => {
    //==>将_x,_y传入fn1.
    fn1(_x, _y);
  };

  fn3 = () => {
    document.onmousemove = null;
  };
  document.onmousemove = fn2;
  ele.onmouseup = fn3;
};
/*
元素运动的函数，可以改变元素的位置属性等
ele表示运动的元素，
option是个对象。里面装需要改变的数据-->{"width":1000}
time 表示运动完成的时间。
fn-->回调函数，待完成
*/
function sport(ele, option, time, fn) {
  let ini = {};
  let aim = {};
  for (var key in option) {
    ini[key] = parseFloat(getComputedStyle(ele)[key]);
    console.log(key);
    console.log(ini[key]);
    aim[key] = option[key];
  }
  let startTime = +new Date();
  ele.time = setInterval(function() {
    let nowTime = +new Date();
    let cha = Math.min(nowTime - startTime, time);
    if (cha == time) {
      clearInterval(ele.time);
    }
    for (var key in option) {
      let res = ((aim[key] - ini[key]) / time) * cha + ini[key];
      ele.style[key] = key == "opacity" ? res : res + "px";
    }
  }, 10);
}

/* 

    @param ele 要执行运动的元素
    @param option 要设置的参数
    @param duration  运动持续的时间
    @param fn 运动执行完毕以后的回调函数
*/

function animate(ele, options, duration, fn) {
  clearInterval(ele.time);
  // 设置初始值 和运动区间
  let start = {},
    range = {};
  for (var key in options) {
    start[key] = parseFloat(css(ele, key));
    range[key] = options[key] - start[key];
  }
  // 记录开始执行时候 的毫秒值
  let startTime = +new Date();
  ele.time = setInterval(() => {
    // 记录下当时的时间
    let nowTime = +new Date();
    // 求时间差值
    let timeDifference = Math.min(nowTime - startTime, duration);

    // 让元素动起来
    for (var attr in options) {
      // left = 单位时间运动的距离 * 运动时间 + 起始值
      // left = 运动距离 / 总的运动时间 * 已经运动的时间 + 起始值
      let result = (range[attr] / duration) * timeDifference + start[attr];
      ele.style[attr] = attr == "opacity" ? result : result + "px";
    }
    // 判断是否停止运动
    if (timeDifference === duration) {
      clearInterval(ele.time);
      fn && fn();
    }
  }, 10);
}

/* 
  让元素 淡出
  @param ele 要设置的元素
  @param duration 淡出的时间
  @param fn 回调函数 
*/
function fadeOut(ele, duration, fn) {
  ele.style.display = "block";
  ele.style.opacity = 1;
  animate(ele, { opacity: 0 }, duration, () => {
    ele.style.display = "none";
    fn && fn();
  });
}
/* 
  让元素 淡入
  @param ele 要设置的元素
  @param duration 淡入的时间
  @param fn 回调函数 
*/
function fadeIn(ele, duration, fn) {
  ele.style.display = "block";
  ele.style.opacity = 0;
  animate(ele, { opacity: 1 }, duration, fn);
}
/*
 * 获取cookie的方法
 * @param {string} key 要获取的cookie的名称
 * @return {string} 这条cookie的值，如果不存在返回undefined
 */
const utils = {
  /**
   *  jsonp请求
   * @param {string} url   请求的地址
   * @param {string} cbName  回调函数名
   * @param {object} query   其他要携带的参数
   */
  jsonp(url, cbName, query) {
    url += `?cb=${cbName}`;
    if (query) {
      for (var key in query) {
        url += `&${key}=${query[key]}`;
      }
    }
    var script = document.createElement("script");
    script.src = url;
    document.body.appendChild(script);
    document.body.removeChild(script)
  },
  getCookie(key) {
    const str = document.cookie;
    const cookie = str.split("; ");
    const obj = cookie.reduce((ob, item) => {
      const arr = item.split("=");
      ob[arr[0]] = decodeURIComponent(arr[1]);
      return ob;
    }, {});
    return obj[key];
  },
  /**
   * 设置cookie
   * @param {string} key 存cookie的名称
   * @param {string} value 存cookie的值
   * @param {object} [option] 可选参数 expires过期时间，path就是路径，比如 {expires: 7, path: '/'} 就是存一条7天后过期的根目录的cookie
   */
  setCookie(key, value, option) {
    let str = `${key}=${encodeURIComponent(value)}`;
    // 如果option传了
    if (option) {
      // 再判断传了那些属性
      if (option.expires) {
        // 过期时间
        var date = new Date();
        date.setDate(date.getDate() + option.expires);
        str += `;expires=${date.toUTCString()}`;
      }
      if (option.path) {
        // 路径
        str += `;path=${option.path}`;
      }
    }
    document.cookie = str;
  },
  /**
   * ajax get请求
   * @param {string} url ==>请求的地址
   * @param {object} query==>请求索要携带的参数
   * @param {function} fn==>求情数据返回之后的回调
   * @param {boolean} [isJson] ==>请求的参数是否为json
   */
  get(url, query, fn, isJson = true) {
    if (query) {
      url += "?";
      for (var key in query) {
        url += `${key}=${query[key]}&`;
      }
      //结束后多一个&
      url = url.slice(0, -1);
    }
    // 创建核心对象
    /**
     * 四部曲--创建核心对象，在使用open连接，send发送，onreadystatechange监听状态
     */
    var xhr = new XMLHttpRequest();
    xhr.open("get", url);
    xhr.send();
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        //请求成功财智星
        if (xhr.status === 200)
          var respText = isJson
            ? JSON.parse(xhr.responseText)
            : xhr.responseText;
        //逻辑短路，fn有效才能被调用
        fn && fn(respText);
      }
    };
  },
  /**
   * ajax post请求
   * @param {string} url 请求的地址
   * @param {object} query 请求所要携带的参数
   * @param {function} fn 请求数据返回之后的回调
   * @param {boolean}  [isJson] 请求的数据是否为json，默认为true
   */
  post(url, query, fn, isJson = true) {
    var str = "";
    if (query) {
      for (var key in query) {
        str += `${key}=${query[key]}&`;
      }
      str = str.slice(0, -1);
    }
    //四部曲+一个setRequestHeader的设置
    var xhr = new XMLHttpRequest();
    xhr.open("post", url);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.send(str);
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          fn && fn(isJson ? JSON.parse(xhr.responseText) : xhr.responseText);
        }
      }
    };
  },
 /**
   *
   * @param {srging} url
   * @param {object} query
   * @param {boolean} isJson
   */
  fetch(url, query, isJson = true) {
    if (query) {
      url += "?";
      for (var key in query) {
        url += `${key}=${query[key]}&`;
      }
      url = url.slice(0, -1);
    }
    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest();
      xhr.open("get", url);
      xhr.send();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            resolve(isJson ? JSON.parse(xhr.responseText) : xhr.responseText);
          } else {
            reject();
          }
        }
      };
    });
  }
};
